using System;
using System.ComponentModel;

namespace VisionConfig
{
	public abstract class HTool : IDisposable
	{
		[EditorBrowsable(EditorBrowsableState.Never)]
		public static readonly IntPtr UNDEF = new IntPtr(-1);

		private IntPtr handle;

		private bool attached;

		private bool suppressedFinalization;

		[EditorBrowsable(EditorBrowsableState.Never)]
		public IntPtr Handle
		{
			get
			{
				return this.handle;
			}
		}

		internal HTool()
			: this(HTool.UNDEF)
		{
		}

		internal HTool(IntPtr handle)
		{
			this.handle = handle;
			this.attached = true;
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public void Detach()
		{
			this.attached = false;
			GC.SuppressFinalize(this);
			this.suppressedFinalization = true;
		}

		public bool IsInitialized()
		{
			return this.handle != HTool.UNDEF;
		}

		~HTool()
		{
			try
			{
				this.Dispose(false);
			}
			catch (Exception)
			{
			}
		}

		private void Dispose(bool disposing)
		{
			if (this.handle != HTool.UNDEF)
			{
				if (this.attached)
				{
					this.ClearHandleResource();
				}
				this.handle = HTool.UNDEF;
			}
			if (disposing)
			{
				GC.SuppressFinalize(this);
				this.suppressedFinalization = true;
			}
			GC.KeepAlive(this);
		}

		void IDisposable.Dispose()
		{
			this.Dispose(true);
		}

		public virtual void Dispose()
		{
			this.Dispose(true);
		}

		[EditorBrowsable(EditorBrowsableState.Never)]
		public void InvalidateWithoutDispose()
		{
			this.handle = HTool.UNDEF;
			this.attached = false;
			GC.SuppressFinalize(this);
			this.suppressedFinalization = true;
			GC.KeepAlive(this);
		}

		internal void Store(IntPtr proc, int parIndex)
		{
			HalconAPI.StoreIP(proc, parIndex, this.handle);
		}

		internal int Load(IntPtr proc, int parIndex, int err)
		{
			if (this.handle != HTool.UNDEF)
			{
				throw new HalconException("Undisposed tool instance when loading output parameter");
			}
			if (HalconAPI.IsFailure(err))
			{
				return err;
			}
			err = HalconAPI.LoadIP(proc, parIndex, err, out this.handle);
			this.attached = true;
			if (this.suppressedFinalization)
			{
				this.suppressedFinalization = false;
				GC.ReRegisterForFinalize(this);
			}
			return err;
		}

		protected abstract void ClearHandleResource();

		[EditorBrowsable(EditorBrowsableState.Never)]
		public static HTuple ConcatArray(HTool[] tools)
		{
			IntPtr[] array = new IntPtr[tools.Length];
			for (int i = 0; i < tools.Length; i++)
			{
				array[i] = tools[i].handle;
			}
			return new HTuple(array);
		}

		public static implicit operator IntPtr(HTool tool)
		{
			return tool.handle;
		}

		public static implicit operator HTuple(HTool tool)
		{
			return new HTuple(tool.handle);
		}
	}
}
